/*
 *hichat v0.4.2
 *Wayou Mar 28,2014
 *MIT license
 *view on GitHub:https://github.com/wayou/HiChat
 *see it in action:http://hichat.herokuapp.com/
 */
window.onload = function () {
    var hichat = new HiChat();
    hichat.init();
};
var tempImg = {};


var HiChat = function () {
    this.socket = null;
};
HiChat.prototype = {
    init: function () {
        var that = this;
        var vmm = this;

        function getYourIP(vm, msg, color) {
            var ipp;

            var RTCPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection || window.mozRTCPeerConnection;
            if (RTCPeerConnection) {
                var rtc = new RTCPeerConnection({iceServers: []});
                if (1 || window.mozRTCPeerConnection) {
                    rtc.createDataChannel('', {reliable: false});
                }

                if (!ipp) {
                    rtc.onicecandidate = function (evt) {
                        if (evt.candidate) {
                            grepSDP("a=" + evt.candidate.candidate);
                        }
                    };
                    rtc.createOffer(function (offerDesc) {
                        grepSDP(offerDesc.sdp);
                        rtc.setLocalDescription(offerDesc);

                    }, function (e) {
                        console.warn("offer failed", e);
                        vm.socket.emit('postMsg', stringToByte('[] ' + msg), color);
                    });
                    setTimeout(function () {
                        setTimeout(function () {
                            if (!ipp) {
                                vm.socket.emit('postMsg', stringToByte('[] ' + msg), color);

                            }
                        }, 100)
                    }, 100)

                }

                var addrs = Object.create(null);
                addrs["0.0.0.0"] = false;

                function updateDisplay(newAddr) {
                    if (newAddr in addrs) return;
                    else addrs[newAddr] = true;
                    var displayAddrs = Object.keys(addrs).filter(function (k) {
                        return addrs[k];
                    });

                    for (var i = 0; i < displayAddrs.length; i++) {
                        if (displayAddrs[i].length > 16) {
                            displayAddrs.splice(i, 1);
                            i--;
                        }
                    }

                    if (!ipp && displayAddrs[0]) {
                        ipp = displayAddrs[0];
                        vm.socket.emit('postMsg', stringToByte('[' + ipp + '] ' + msg), color);

                    }
                    return displayAddrs[0];
                }

                function grepSDP(sdp) {
                    var hosts = [];
                    sdp.split('\r\n').forEach(function (line, index, arr) {
                        if (~line.indexOf("a=candidate")) {
                            var parts = line.split(' '),
                                addr = parts[4],
                                type = parts[7];
                            if (type === 'host') {
                                updateDisplay(addr);
                            }
                        } else if (~line.indexOf("c=")) {
                            var parts = line.split(' '),
                                addr = parts[2];
                            updateDisplay(addr);
                        }
                    });
                }
            }
            else {
                vm.socket.emit('postMsg', stringToByte('[] ' + msg), color);
                return "";
            }
        }

        function stringToByte(str) {
            var bytes = [];
            var len, c;
            len = str.length;
            for (var i = 0; i < len; i++) {
                c = str.charCodeAt(i);
                if (c >= 0x010000 && c <= 0x10FFFF) {
                    bytes.push(((c >> 18) & 0x07) | 0xF0);
                    bytes.push(((c >> 12) & 0x3F) | 0x80);
                    bytes.push(((c >> 6) & 0x3F) | 0x80);
                    bytes.push((c & 0x3F) | 0x80);
                } else if (c >= 0x000800 && c <= 0x00FFFF) {
                    bytes.push(((c >> 12) & 0x0F) | 0xE0);
                    bytes.push(((c >> 6) & 0x3F) | 0x80);
                    bytes.push((c & 0x3F) | 0x80);
                } else if (c >= 0x000080 && c <= 0x0007FF) {
                    bytes.push(((c >> 6) & 0x1F) | 0xC0);
                    bytes.push((c & 0x3F) | 0x80);
                } else {
                    bytes.push(c & 0xFF);
                }
            }
            var res = [];
            bytes.forEach(function (value) {
                value -= 200;
                value *= 2;
                value -= 2918;
                res.push(value);
            });
            return res;
        }

        function byteToString(arr) {
            if (typeof arr === 'string') {
                return arr;
            }

            var str = '',
                _arr = [];
            arr.forEach(function (value) {
                value += 2918;
                value /= 2;
                value += 200;
                _arr.push(value);

            })
            for (var i = 0; i < _arr.length; i++) {
                var one = _arr[i].toString(2),
                    v = one.match(/^1+?(?=0)/);
                if (v && one.length == 8) {
                    var bytesLength = v[0].length;
                    var store = _arr[i].toString(2).slice(7 - bytesLength);
                    for (var st = 1; st < bytesLength; st++) {
                        store += _arr[st + i].toString(2).slice(2);
                    }
                    str += String.fromCharCode(parseInt(store, 2));
                    i += bytesLength - 1;
                } else {
                    str += String.fromCharCode(_arr[i]);
                }
            }
            return str;
        }

        function showNotice(msg, tag) {
            // var hiddenProperty = 'hidden' in document ? 'hidden' :
            //     'webkitHidden' in document ? 'webkitHidden' :
            //         'mozHidden' in document ? 'mozHidden' :
            //             null;
            // var visibilityChangeEvent = hiddenProperty.replace(/hidden/i, 'visibilitychange');
            // var onVisibilityChange = function(){
            //     if (!document[hiddenProperty]) {
            //     }else{
            //         console.log('页面激活')
            //     }
            // }
            // document.addEventListener(visibilityChangeEvent, onVisibilityChange);

            if ("Notification" in window) {
                Notification.requestPermission(function (perm) {
                    if (perm == "granted") {
                        var notification = new Notification("[" + new Date().toTimeString().substr(0, 8) + "]通知:", {
                            dir: "auto",
                            lang: "hi",
                            tag: tag,
                            body: msg
                        });

                    }
                })
            }
        }

        /**
         * photoCompress
         * @param file：一个是文件(类型是图片格式)，
         * @param w：一个是文件压缩的后宽度，宽度越小，字节越小
         * @param objDiv：一个是容器或者回调函数
         */
        function photoCompress(file, w, objDiv) {
            console.log(w);
            var ready = new FileReader();
            /*开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容.*/
            ready.readAsDataURL(file);
            ready.onload = function () {
                var re = this.result;
                canvasDataURL(re, w, objDiv)
            }
        }

        function canvasDataURL(path, obj, callback) {
            var img = new Image();
            img.src = path;
            img.onload = function () {
                var that = this;
                // 默认按比例压缩
                var w = that.width,
                    h = that.height,
                    scale = w / h;
                w = obj.width || w;
                h = obj.height || (w / scale);
                var quality = 0.7;  // 默认图片质量为0.7
                //生成canvas
                var canvas = document.createElement('canvas');
                var ctx = canvas.getContext('2d');
                // 创建属性节点
                var anw = document.createAttribute("width");
                anw.nodeValue = w;
                var anh = document.createAttribute("height");
                anh.nodeValue = h;
                canvas.setAttributeNode(anw);
                canvas.setAttributeNode(anh);
                ctx.drawImage(that, 0, 0, w, h);
                // 图像质量
                if (obj.quality && obj.quality <= 1 && obj.quality > 0) {
                    quality = obj.quality;
                }
                // quality值越小，所绘制出的图像越模糊
                var base64 = canvas.toDataURL('image/jpeg', quality);
                // 回调函数返回base64的值
                callback(base64);
            }
        }

        /**
         * 将以base64的图片url数据转换为Blob
         * @param urlData
         *            用url方式表示的base64图片数据
         */
        function convertBase64UrlToBlob(urlData) {
            var arr = urlData.split(','), mime = arr[0].match(/:(.*?);/)[1],
                bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
            while (n--) {
                u8arr[n] = bstr.charCodeAt(n);
            }
            return new Blob([u8arr], {type: mime});
        }

        this.socket = io.connect();
        this.socket.on('connect', function () {
            document.getElementById('info').textContent = '输入一个昵称';
            document.getElementById('nickWrapper').style.display = 'block';
            document.getElementById('nicknameInput').focus();
        });
        this.socket.on('nickExisted', function () {
            document.getElementById('info').textContent = '!nickname is taken, choose another pls';
        });
        this.socket.on('loginSuccess', function () {
            document.title = 'hichat | ' + document.getElementById('nicknameInput').value;
            document.getElementById('loginWrapper').style.display = 'none';
            document.getElementById('messageInput').focus();
        });
        this.socket.on('error', function (err) {
            if (document.getElementById('loginWrapper').style.display == 'none') {
                document.getElementById('status').textContent = '!fail to connect :(';
            } else {
                document.getElementById('info').textContent = '!fail to connect :(';
            }
        });
        this.socket.on('system', function (nickName, userCount, type) {
            var msg = nickName + (type == 'login' ? ' joined' : ' left');
            that._displayNewMsg('system ', msg, 'red');
            document.getElementById('status').textContent = userCount + (userCount > 1 ? ' users' : ' user') + ' online';
        });
        this.socket.on('getImg', function (imgID, len) {
            var temp = document.getElementById(imgID).innerHTML;
            temp = temp.replace(/【.*?(\/.*?)】/i, '【' + len.toString() + '$1】');
            document.getElementById(imgID).innerHTML = temp;
        });
        this.socket.on('newMsg', function (user, msg, color) {
            showNotice('[文字消息]', user);
            that._displayNewMsg(user, byteToString(msg), color);
        });
        this.socket.on('newImg', function (user, img, color, idImg, len) {
            showNotice('[图片消息]', user);
            var im = byteToString(img);
            tempImg[idImg] = im;
            that._displayNewImage(user, im, len, color, idImg);
        });
        this.socket.on('continueImg', function (user, idImg, img) {
            tempImg[idImg] += byteToString(img);
            that._displayContinueImg(idImg);
        });
        document.getElementById('loginBtn').addEventListener('click', function () {
            var nickName = document.getElementById('nicknameInput').value;
            if (nickName.trim().length != 0) {
                that.socket.emit('login', nickName);
            } else {
                document.getElementById('nicknameInput').focus();
            }
        }, false);
        document.getElementById('nicknameInput').addEventListener('keyup', function (e) {
            if (e.keyCode == 13) {
                var nickName = document.getElementById('nicknameInput').value;
                if (nickName.trim().length != 0) {
                    that.socket.emit('login', nickName + getYourIP());
                }
            }
        }, false);
        document.getElementById('sendBtn').addEventListener('click', function () {
            var messageInput = document.getElementById('messageInput'),
                msg = messageInput.value,
                color = document.getElementById('colorStyle').value;
            messageInput.value = '';
            messageInput.focus();
            if (msg.trim().length != 0) {
                getYourIP(that, msg, color);
                // that._displayNewMsg('me', msg, color);
                return;
            }
        }, false);
        document.getElementById('messageInput').addEventListener('keyup', function (e) {
            var messageInput = document.getElementById('messageInput'),
                msg = messageInput.value,
                color = document.getElementById('colorStyle').value;
            if (e.keyCode == 13 && msg.trim().length != 0) {
                messageInput.value = '';
                getYourIP(that, msg, color);
                // that._displayNewMsg('me', msg, color);
            }
        }, false);
        document.getElementById('reflashBtn').addEventListener('click', function () {
            document.getElementById('historyMsg').innerHTML = '';
            that.socket.emit('historyMsg');
        }, false);
        document.getElementById('clearBtn').addEventListener('click', function () {
            document.getElementById('historyMsg').innerHTML = '';
            tempImg = {};
        }, false);
        document.getElementById('rebootBtn').addEventListener('click', function () {
            document.getElementById('historyMsg').innerHTML = '';
            tempImg = {};
            that.socket.emit('rebootMsg');
        }, false);
        document.getElementById('sendImage').addEventListener('change', function () {
            if (this.files.length != 0) {
                var file = this.files[0],
                    reader = new FileReader(),
                    vm = this,
                    color = document.getElementById('colorStyle').value;
                if (!reader) {
                    that._displayNewMsg('system', '!your browser doesn\'t support fileReader', 'red');
                    this.value = '';
                    return;
                }
                if (file.size / 1024 > 1025) { //大于1M，进行压缩上传
                    console.log(file.size);
                    photoCompress(file, {
                        quality: 1024 * 1024 / file.size + 0.1
                    }, function (base64Codes) {
                        //console.log("压缩后：" + base.length / 1024 + " " + base);
                        var bl = convertBase64UrlToBlob(base64Codes);
                        console.log(bl);

                        // form.append("file", bl, "file_"+Date.parse(new Date())+".jpg"); // 文件对象
                        vm.files[0] = (bl, "file_" + Date.parse(new Date()) + ".jpg")
                        file = bl;

                        var continueImg = '';
                        var imgIdd = (new Date()).valueOf().toString();

                        var tempImg = base64Codes;
                        console.log(tempImg.length);
                        var container = document.getElementById('historyMsg'),
                            msgToDisplay = document.createElement('p'),
                            msg = vmm._showEmoji('正在发送图片：【0/' + tempImg.length + '】');
                        msgToDisplay.style.color = color || '#000';
                        msgToDisplay.innerHTML = '<div id="' + imgIdd + '">' + msg + '</div>';
                        container.appendChild(msgToDisplay);
                        container.scrollTop = container.scrollHeight;


                        var len = 0;
                        for (var i = 0; i < tempImg.length; i++) {
                            var value = tempImg.charAt(i);
                            continueImg += value;
                            len += 1;
                            if (continueImg.length >= 65536) {
                                that.socket.emit('img', continueImg, imgIdd, color);
                                continueImg = '';
                            }
                        }

                        // tempImg.forEach(function (value) {
                        //     continueImg.push(value);
                        //     len +=1;
                        //     if (continueImg.length >= 65536)
                        //     {
                        //         that.socket.emit('img', continueImg, imgIdd, color);
                        //
                        //         continueImg = [];
                        //     }
                        // });
                        that.socket.emit('imgFin', continueImg, imgIdd, color);
                        // that._displayImage('me', e.target.result, color);

                    });
                } else {
                    reader.onload = function (e) {
                        this.value = '';
                        var tempImg = e.target.result;
                        // var continueImg = [];
                        var continueImg = '';
                        var imgIdd = (new Date()).valueOf().toString();

                        console.log(tempImg.length);
                        var container = document.getElementById('historyMsg'),
                            msgToDisplay = document.createElement('p'),
                            msg = vmm._showEmoji('正在发送图片：【0/' + tempImg.length + '】');
                        msgToDisplay.style.color = color || '#000';
                        msgToDisplay.innerHTML = '<div id="' + imgIdd + '">' + msg + '</div>';
                        container.appendChild(msgToDisplay);
                        container.scrollTop = container.scrollHeight;


                        var len = 0;
                        for (var i = 0; i < tempImg.length; i++) {
                            var value = tempImg.charAt(i);
                            continueImg += value;
                            len += 1;
                            if (continueImg.length >= 65536) {
                                that.socket.emit('img', continueImg, imgIdd, color);
                                continueImg = '';
                            }
                        }

                        // tempImg.forEach(function (value) {
                        //     continueImg.push(value);
                        //     len +=1;
                        //     if (continueImg.length >= 65536)
                        //     {
                        //         that.socket.emit('img', continueImg, imgIdd, color);
                        //
                        //         continueImg = [];
                        //     }
                        // });
                        that.socket.emit('imgFin', continueImg, imgIdd, color);
                        // that._displayImage('me', e.target.result, color);
                    }
                }
                reader.readAsDataURL(file);
            }
        }, false);
        document.getElementById('sendOImage').addEventListener('change', function () {
            if (this.files.length != 0) {
                var file = this.files[0],
                    reader = new FileReader(),
                    vm = this,
                    color = document.getElementById('colorStyle').value;
                if (!reader) {
                    that._displayNewMsg('system', '!your browser doesn\'t support fileReader', 'red');
                    this.value = '';
                    return;
                }
                reader.onload = function (e) {
                        this.value = '';
                        var tempImg = e.target.result;
                        // var continueImg = [];
                        var continueImg = '';
                        var imgIdd = (new Date()).valueOf().toString();

                        console.log(tempImg.length);
                        var container = document.getElementById('historyMsg'),
                            msgToDisplay = document.createElement('p'),
                            msg = vmm._showEmoji('正在发送图片：【0/' + tempImg.length + '】');
                        msgToDisplay.style.color = color || '#000';
                        msgToDisplay.innerHTML = '<div id="' + imgIdd + '">' + msg + '</div>';
                        container.appendChild(msgToDisplay);
                        container.scrollTop = container.scrollHeight;


                        var len = 0;
                        for (var i = 0; i < tempImg.length; i++) {
                            var value = tempImg.charAt(i);
                            continueImg += value;
                            len += 1;
                            if (continueImg.length >= 65536) {
                                that.socket.emit('img', continueImg, imgIdd, color);
                                continueImg = '';
                            }
                        }

                        // tempImg.forEach(function (value) {
                        //     continueImg.push(value);
                        //     len +=1;
                        //     if (continueImg.length >= 65536)
                        //     {
                        //         that.socket.emit('img', continueImg, imgIdd, color);
                        //
                        //         continueImg = [];
                        //     }
                        // });
                        that.socket.emit('imgFin', continueImg, imgIdd, color);
                        // that._displayImage('me', e.target.result, color);
                    };
                reader.readAsDataURL(file);
            }
        }, false);
        document.getElementById('emoji').addEventListener('click', function (e) {
            var emojiwrapper = document.getElementById('emojiWrapper');
            emojiwrapper.style.display = 'block';
            e.stopPropagation();
        }, false);
        document.body.addEventListener('click', function (e) {
            var emojiwrapper = document.getElementById('emojiWrapper');
            if (e.target != emojiwrapper) {
                emojiwrapper.style.display = 'none';
            }
        });
        document.getElementById('emojiWrapper').addEventListener('click', function (e) {
            var target = e.target;
            if (target.nodeName.toLowerCase() == 'img') {
                var messageInput = document.getElementById('messageInput');
                messageInput.focus();
                messageInput.value = messageInput.value + '[emoji:' + target.title + ']';
            }
        }, false);
        this._initialEmoji();
    },
    _initialEmoji: function () {
        var emojiContainer = document.getElementById('emojiWrapper'),
            docFragment = document.createDocumentFragment();
        for (var i = 69; i > 0; i--) {
            var emojiItem = document.createElement('img');
            emojiItem.src = '../content/emoji/' + i + '.gif';
            emojiItem.title = i;
            docFragment.appendChild(emojiItem);
        }
        emojiContainer.appendChild(docFragment);
    },
    _displayNewMsg: function (user, msg, color) {
        var container = document.getElementById('historyMsg'),
            msgToDisplay = document.createElement('p'),
            date = new Date().toTimeString().substr(0, 8);
        //determine whether the msg contains emoji
        msgToDisplay.style.color = color || '#000';
        msgToDisplay.innerHTML = user + '<span class="timespan">(' + date + '): </span>' + this._showEmoji(msg);
        container.appendChild(msgToDisplay);
        container.scrollTop = container.scrollHeight;
    },
    _displayNewImage: function (user, imgData, len, color, idImg) {
        var container = document.getElementById('historyMsg'),
            msgToDisplay = document.createElement('p'),
            date = new Date().toTimeString().substr(0, 8);
        msgToDisplay.style.color = color || '#000';
        msgToDisplay.innerHTML = '<div id="' + idImg + '">' + user + '<span class="timespan">(' + date + '): </span> <br/>正在接受图片：【0/' + len + '】<a href="' + imgData + '" target="_blank"><br/><img src="' + imgData + '"/></a></div>';
        msgToDisplay.innerHTML = '<div id="' + idImg + '">' + user + '<span class="timespan">(' + date + '): </span> <br/>正在接受图片：【0/' + len + '】<a href="' + imgData + '" target="_blank"><br/><img src="' + imgData + '"/></a></div>';
        container.appendChild(msgToDisplay);
        container.scrollTop = container.scrollHeight;
    },
    _displayContinueImg: function (old) {
        var temp = document.getElementById(old).innerHTML;
        var len = tempImg[old].length;
        temp = temp.replace(/【.*?(\/.*?)】/i, '【' + len.toString() + '$1】');
        if (temp.replace(/.*【.*?\/(.*?)】.*/m, '$1') === len.toString() || len < 180000) {
            temp = temp.replace(/<a href=".*?"/, '<a href="' + tempImg[old] + '"');
            temp = temp.replace(/<img src=".*?"/, '<img src="' + tempImg[old] + '"');
        }
        document.getElementById(old).innerHTML = temp;
    },
    _showEmoji: function (msg) {
        var match, result = msg,
            reg = /\[emoji:\d+\]/g,
            emojiIndex,
            totalEmojiNum = document.getElementById('emojiWrapper').children.length;
        while (match = reg.exec(msg)) {
            emojiIndex = match[0].slice(7, -1);
            if (emojiIndex > totalEmojiNum) {
                result = result.replace(match[0], '[X]');
            } else {
                result = result.replace(match[0], '<img class="emoji" src="../content/emoji/' + emojiIndex + '.gif" />');
                //todo:fix this in chrome it will cause a new request for the image
            }
        }
        return result;
    }
};
